package cc.sheji.Service;


import cc.sheji.config.JobConfig;
import cc.sheji.domain.*;
import cc.sheji.exception.CreateJobRuleException;
import cc.sheji.exception.NotEnoughCoinException;
import cc.sheji.exception.TooMoreActionException;
import cc.sheji.exception.TranslateException;
import cc.sheji.reposity.CategoryRepository;
import cc.sheji.reposity.JobRepository;
import cc.sheji.reposity.NoticeRepository;
import cc.sheji.reposity.UserRepository;
import cc.sheji.util.CompareUtil;
import cc.sheji.util.HttpUtil;
import cc.sheji.util.QueryHelp;
import cc.sheji.util.StateCallBack;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class JobService {

    @Autowired
    JobRepository jobRepository;

    @Autowired
    HttpUtil httpUtil;
    @Autowired
    UserService userService;
    @Autowired
    JobConfig jobConfig;
    private Logger log = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    CompareUtil compareUtil;
    String uploadUrl="https://www.shejiai.cc/api/v1/file/upload";
    @Value("${updataPath}")
    String updataPath;
    @Autowired
    NoticeRepository noticeRepository;
    @Autowired
    CategoryRepository categoryRepository;
    static HashMap<String, String> whRaditoMap = new HashMap();

    static {
        whRaditoMap.put("1", " --ar 1:1");
        whRaditoMap.put("2", " --ar 1:2");
        whRaditoMap.put("3", " --ar 4:3");
        whRaditoMap.put("4", " --ar 3:4");
        whRaditoMap.put("5", " --ar 16:9");
        whRaditoMap.put("6", " --ar 9:16");
    }
    static HashMap<String, String> whRaditoMaps = new HashMap();

    static {
        whRaditoMaps.put("1", "1:1");
        whRaditoMaps.put("2", "1:2");
        whRaditoMaps.put("3", "4:3");
        whRaditoMaps.put("4", "3:4");
        whRaditoMaps.put("5", "16:9");
        whRaditoMaps.put("6", "9:16");
    }
    @Autowired
    UserRepository userRepository;
    private String doTaskUrl1 = "https://api.midjourneyapi.xyz/mj/v2/imagine";
    private String doTaskUrl2 = "https://api.midjourneyapi.xyz/mj/v2/blend";
    private String doTaskUrl3 = "https://api.midjourneyapi.xyz/mj/v2/fetch";
    private String Key = "64ba78a75936935a2a8d4ee72ab4c0bb84b3bc52029c4b62eddd9647a7097cba";

    public static String toEnglishUrl(String raw) throws UnsupportedEncodingException {

        // String raw = "中国";
        String content = URLEncoder.encode(raw, "UTF-8");
        String salt = "1435660288";
        // my count
//        String secery = "fb5q0zbG1nfMBfLJpm4G";
//        String appid = "20230427001658492";
        // sheji count
        String secery = "oIcbPFyeSb1kx2NmpLkk";
        String appid = "20230427001658719";
        String testStr = appid + raw + salt + secery;
        String md5Hex1 = DigestUtil.md5Hex(testStr);
        String url = "http://api.fanyi.baidu.com/api/trans/vip/translate" +
                "?q=" + content + "&from=auto&to=en&appid=" + appid + "&salt=" + salt +
                "&sign=" + md5Hex1;
        return url;
    }

    public String hanleEngligh(String json) {
        JSONObject jsonObject = JSONObject.parseObject(json);
//            {"from":"zh","to":"en","trans_result":[{"src":"\u4e2d\u56fd","dst":"China"}]}
        JSONArray transResult = jsonObject.getJSONArray("trans_result");
        if (transResult == null || transResult.size() == 0)
            return null;
        String dst = transResult.getJSONObject(0).getString("dst");
        dst = dst.replaceAll("  ", " ");
        return dst;
    }

    public Job sameProduct(Job job) throws Exception {

        HashMap<String, Object> info = userService.get();

        if (info.get("level").equals(0) && info.get("sameNum").equals(0)) {
            throw new NotEnoughCoinException("请开通权益卡");
        }

        userService.paySameProduct();

        Job job1 = jobRepository.findById(job.getParentId()).get();
        job.setId(null);
        job.setType(3);
        job.setCmd(job1.getCmd());
        job.setAttachment(job1.getAttachment());
        job.setState(0);
        job.setTaskType(1);
        job.setWidth2height(job1.getWidth2height());
        job.setPictureWeight(job1.getPictureWeight());
        job.setStyle(job1.getStyle());
        job.setModule(job1.getModule());
        job.setProductMode(job1.getProductMode());
        job.setBadContent(job1.getBadContent());
        return create(job);
    }

    public Job create(Job job) throws Exception {

        try {
            Optional<User> byId = userRepository.findById(StpUtil.getLoginIdAsLong());
            if(byId!=null){
                User user = byId.get();
                Integer continueTimeLock = user.getContinueTimeLock();
                if(continueTimeLock==null||continueTimeLock!=1){
                    user.setContinueTimeLock(1);
                    Integer continueTime = user.getContinueTime();
                    if(continueTime!=null&&continueTime>0){
                        continueTime++;
                    }else {
                        continueTime=1;
                    }
                    user.setContinueTime(continueTime);
                    Integer monthTime = user.getMonthTime();
                    if(monthTime!=null){
                        monthTime++;
                    }else {
                        monthTime=1;
                    }
                    user.setMonthTime(monthTime);
                    System.out.println("--------normal reach-------------");
                }
                System.out.println("--------normal reach1-------------");
            }
        }catch (Exception e){

            e.printStackTrace();
        }

        String key = "job" + StpUtil.getLoginId();

//        redisTemplate.opsForValue().
        if (redisTemplate.hasKey(key)) {
            throw new TooMoreActionException();
        }

        String[] attachImages = job.getAttachImages();
        boolean samePic = false;

        if (attachImages != null) {
            if (attachImages.length > 1)
                for (int i = 0; i < attachImages.length; i++) {
                    for (int k = i + 1; k < attachImages.length; k++) {
                        String url1 = attachImages[i];
                        String url2 = attachImages[k];
                        url1 = url1.replaceAll("https://www.shejiai.cc:443/v1/image/", "");
                        url2 = url2.replaceAll("https://www.shejiai.cc:443/v1/image/", "");
                        url1 = updataPath + url1;
                        url2 = updataPath + url2;
                        if (compareUtil.compareFiles(url1, url2)) {
                            samePic = true;
                        }
                    }
                }
        }

        if (samePic) {
            throw new CreateJobRuleException("不能上传一样图片");
        }


        redisTemplate.opsForValue().set(key, new Date(), 30, TimeUnit.SECONDS);
        job.setId(null);
        job.setUserId(StpUtil.getLoginIdAsLong());
        String cmd = "" + job.getCmd().replaceAll("  ", " ");
        List<Category> all = categoryRepository.findAll(null);
        if (all != null)
            for (Category category : all) {
                String name = category.getName();
                String englishName = category.getEnglishName();
                if (englishName != null && name != null)
                    cmd = cmd.replaceAll(name, englishName);
            }

        Pattern p = Pattern.compile("[\u4e00-\u9fa5]");
        Matcher m = p.matcher(cmd);
        if (m.find()) {
            int time = 0;
            boolean finish = false;
            while (time < 3) {
                String translate = hanleEngligh(httpUtil.getToString(toEnglishUrl(cmd)));
                if (translate != null) {
                    finish = true;
                    cmd = translate;
                    break;
                }
                Thread.sleep(2000);
            }
            if (!finish)
                throw new TranslateException("翻译功能异常");
        }


        cmd = cmd.trim();
        String addCmd = "";
        if (cmd.length() != 0) {
            addCmd = addCmd + "" + cmd;
        }
        if (job.getStyle() != null) {
            try {
                Long styleId = Long.parseLong("" + job.getStyle());
                Optional<Category> byId = categoryRepository.findById(styleId);
                if (byId != null) {
                    Category category = byId.get();
                    if (category != null) {

                        String englishName = category.getEnglishName();
                        if (englishName != null && englishName.length() > 0)
                            addCmd = addCmd + " " + englishName;
                    }

                }
            } catch (Exception e) {
            }
        }
        addCmd = addCmd.replaceAll("-", " ");
        addCmd = addCmd.replace(" tile ", " --tile ");
        addCmd = addCmd.replace(" tile", " --tile");
        addCmd = addCmd.replaceAll("  ", " ");
        job.setFullTextCmd(addCmd);
        String badContent = job.getBadContent();
        if (badContent == null || badContent.toLowerCase().equals("null")) {
            badContent = "";
        }
        Matcher m1 = p.matcher(badContent);
        if (m1.find()) {
            int time = 0;
            boolean finish = false;
            while (time < 3) {
                String translate = hanleEngligh(httpUtil.getToString(toEnglishUrl(badContent)));
                if (translate != null) {
                    finish = true;
                    badContent = translate;
                    break;
                }
                Thread.sleep(2000);
            }
            if (!finish)
                throw new TranslateException("翻译功能异常");
        }
        badContent = badContent.replaceAll("-", " ");
        badContent = badContent.replaceAll("  ", " ");
        job.setBadContentFullText(badContent.trim());
        switch (job.getModule()) {
            case 4:
                addCmd += " --v 5.1";
                break;
            case 5:
                addCmd += " --v 5.2";
                break;
            case 6:
                addCmd += " --v 5 --niji 5";
                break;
            case 7:
                addCmd += " --v 5 --c 10";
                break;
            case 8:
                addCmd += " --v 5 ";
                break;
        }
        Job finalJob = job;
        //图片纵横比
        String whRatio = " --ar 1:1";
        String temRadio = whRaditoMap.get("" + job.getWidth2height());
        if (temRadio != null) {
            whRatio = temRadio;
        }
        PayInfo payInfo = new PayInfo();
        Integer type = job.getType();
        if (type == null)
            type = 0;
        payInfo.setType(type);
        if (type == 1 || type == 2 || type == 7)
            userService.payTask(StpUtil.getLoginIdAsLong(), payInfo(payInfo));
        job = jobRepository.save(job);
        return job;
    }

    public Job get(@PathVariable("id") Long id) {

        Job job = jobRepository.findById(id).get();
//        JSONObject jsonObj  = new JSONObject();
//        jsonObj.put("task_id",job.getTaskId());
//        String jsonstr =jsonObj.toJSONString();
//        Map<String, String> headers = new HashMap<>();
//        headers.put("X-API-KEY", Key);
//        if(job.getState()==0||job.getState()==6||job.getState()==7){
//            httpUtil.postJsonToString(doTaskUrl3, jsonstr, headers, new StateCallBack() {
//                @Override
//                public void onSuccess(String json) throws Exception {
//                    JSONObject jsonObject = JSONObject.parseObject(json);
//                    if (jsonObject.getString("status").equals("finished")) {
////                        job.setState(4);
//                        JSONArray jsonArray  = new JSONArray();
//                        jsonArray.add(jsonObject.getJSONObject("task_result").getString("image_url"));
//                        job.setFinalResult(jsonArray.toJSONString());
//                        job.setResult(jsonArray.toJSONString());
//                        job.setImageId(jsonObject.getJSONObject("task_result").getString("image_id"));
//                        System.out.println("fetch task:" + json);
//                        json = "" + json;
//                        job.setDataResult(json);
//                        job.setFinishTime(new Date());
//                        jobRepository.save(job);
//                        download(job);
////                        Notice notice = new Notice();
////                        notice.setJobId(job.getId());
////                        notice.setContent("AI生成完毕");
////                        notice.setType(2);
////                        notice.setStatus(0);
////                        notice.setUserId(job.getUserId());
////                        notice.setName("AI生成完毕可点击查看");
////                        noticeRepository.save(notice);
//                    }
//                    if (jsonObject.getString("status").equals("failed")) {
//                        Notice notice = new Notice();
//                        notice.setJobId(job.getId());
//                        notice.setContent("系统出错，带来不便，敬请谅解！请您重新提交任务。");
//                        notice.setType(2);
//                        notice.setStatus(0);
//                        notice.setUserId(job.getUserId());
//                        notice.setName("系统出错");
//                        noticeRepository.save(notice);
//                        job.setState(10);
//                        job.setErrorState(1);
//                        job.setNoticeState(1);
//                        JSONArray jsonArray  = new JSONArray();
//                        System.out.println("fetch task:" + json);
//                        json = "" + json;
//                        job.setErrorMessages(jsonObject.getJSONObject("task_result").getString("error_messages"));
//                        job.setFinishTime(new Date());
//                        jobRepository.save(job);
//
//                    }
//
//                }
//                @Override
//                public void onFail(String e) {
//                    System.out.println("查询结果报错 error:" + e);
//                }
//            });
//        }
        return job;
    }
    public Job gets(@PathVariable("id") Long id) {

        Job job = jobRepository.findById(id).get();
        JSONObject jsonObj  = new JSONObject();
        jsonObj.put("task_id",job.getTaskId());
        String jsonstr =jsonObj.toJSONString();
        Map<String, String> headers = new HashMap<>();
        headers.put("X-API-KEY", Key);
        if(job.getState()==0||job.getState()==6||job.getState()==7){
            httpUtil.postJsonToString(doTaskUrl3, jsonstr, headers, new StateCallBack() {
                @Override
                public void onSuccess(String json) throws Exception {
                    JSONObject jsonObject = JSONObject.parseObject(json);
                    if (jsonObject.getString("status").equals("finished")) {
//                        job.setState(4);
                        JSONArray jsonArray  = new JSONArray();
                        jsonArray.add(jsonObject.getJSONObject("task_result").getString("image_url"));
                        job.setFinalResult(jsonArray.toJSONString());
                        job.setResult(jsonArray.toJSONString());
                        job.setImageId(jsonObject.getJSONObject("task_result").getString("image_id"));
                        System.out.println("fetch task:" + json);
                        json = "" + json;
                        job.setDataResult(json);
                        job.setFinishTime(new Date());
                        jobRepository.save(job);
                        download(job);
//                        Notice notice = new Notice();
//                        notice.setJobId(job.getId());
//                        notice.setContent("AI生成完毕");
//                        notice.setType(2);
//                        notice.setStatus(0);
//                        notice.setUserId(job.getUserId());
//                        notice.setName("AI生成完毕可点击查看");
//                        noticeRepository.save(notice);
                    }
                    if (jsonObject.getString("status").equals("failed")) {
                        Notice notice = new Notice();
                        notice.setJobId(job.getId());
                        notice.setContent("系统出错，带来不便，敬请谅解！请您重新提交任务。");
                        notice.setType(2);
                        notice.setStatus(0);
                        notice.setUserId(job.getUserId());
                        notice.setName("系统出错");
                        noticeRepository.save(notice);
                        job.setState(10);
                        job.setErrorState(1);
                        job.setNoticeState(1);
                        JSONArray jsonArray  = new JSONArray();
                        System.out.println("fetch task:" + json);
                        json = "" + json;
                        job.setErrorMessages(jsonObject.getJSONObject("task_result").getString("error_messages"));
                        job.setFinishTime(new Date());
                        jobRepository.save(job);

                    }

                }
                @Override
                public void onFail(String e) {
                    System.out.println("查询结果报错 error:" + e);
                }
            });
        }
        return job;
    }
    public void download(Job job) throws Exception {

        if (job == null)
            return;
        try {
            job.setState(3);
            jobRepository.save(job);
            List<String> imageList = new ArrayList<>();
            JSONArray resultImages = job.getResultImages();
            for (int i = 0; i < resultImages.size(); i++) {

                try {
                    String imageUrl = resultImages.getString(i);
                    if(imageUrl==null||imageUrl.length()<5){
                        continue;
                    }
                    String filePath = httpUtil.downloadImage(imageUrl, updataPath);

                    if(filePath==null){
                        filePath = httpUtil.downloadImage(imageUrl, updataPath);

                    }

                    if(filePath==null||filePath.length()<6)
                        continue;

                    String result = httpUtil.updataFile(uploadUrl, filePath);
                    if(result==null){
                        result = httpUtil.updataFile(uploadUrl, filePath);

                    }
                    if(result==null)
                        continue;
                    JSONObject json = JSONObject.parseObject(result);
                    String finalImageUrl = json.getString("data");
                    imageList.add(finalImageUrl);
                } catch (Throwable e) {
                    System.out.println("download error " + e.getMessage());
                }
            }
            if(imageList.size()==0){
                job.setState(2);
                Job save = jobRepository.save(job);
                System.out.println("save:"+save);
            }else {
                job.setFinalResultImages(imageList);
                job.setState(4);
                jobRepository.save(job);
                Notice notice = new Notice();
                notice.setJobId(job.getId());
                notice.setContent("AI生成完毕");
                notice.setType(2);
                notice.setStatus(0);
                notice.setUserId(job.getUserId());
                notice.setName("AI生成完毕可点击查看");
                noticeRepository.save(notice);
            }
        } catch (Throwable e) {
            job.setState(2);
            jobRepository.save(job);

        }

    }
    public List<Job> list(JobQueryCriteria criteria, Pageable pageable) {

        Sort order = Sort.by(Sort.Direction.DESC, "createTime");
        if (criteria.getOrderType() != null && 1 == criteria.getOrderType()) {
            order = Sort.by(Sort.Direction.ASC, "createTime");
        }
        pageable = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), order);
        Page<Job> page = jobRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        return page.getContent();
    }

    public Job update(Job job) {

        Job job1 = jobRepository.findById(job.getId()).get();
        return jobRepository.save(job1);
    }


    public Map payInfo(PayInfo payInfo) {

        Map<String, Object> map = new HashMap<>();

        map.put("coin", 0);
        map.put("fastCoin", 0);
        map.put("permissionTime", 1);
        map.put("fastTime", 0);
        map.put("tryTime", 0);
        map.put("type", payInfo.type);
        map.put("permissionTime", 1);
        HashMap<String, Object> info = userService.get();
        map.put("user", info);
        Integer level = (Integer) info.get("level");
        Integer freeFastNum = (Integer) info.get("freeFastNum");
        Integer vipNum0 = (Integer) info.get("vipNum0");
        map.put("todayTime", (Integer) info.get("toDayNum"));

        switch (payInfo.type) {
            case 1:
                if (level > 0) {
                    map.put("coin", 0);
                    map.put("fastCoin", 0);
                    map.put("permissionTime", 1);
                    map.put("fastTime", 0);
                    map.put("tryTime", 0);

                } else {
                    map.put("fastCoin", 0);
                    map.put("permissionTime", 0);
                    map.put("fastTime", 0);
                    if (vipNum0 > 0) {
                        map.put("coin", 0);
                        map.put("tryTime", 1);
                    } else {
                        map.put("coin", jobConfig.nomalTaskCoin);
                        map.put("tryTime", 0);
                    }
                }
                break;
            case 2:
                if (level > 0) {
                    if (freeFastNum > 0) {
                        map.put("coin", 0);
                        map.put("fastCoin", 0);
                        map.put("permissionTime", 1);
                        map.put("fastTime", 1);
                        map.put("tryTime", 0);
                    } else {
                        map.put("coin", 0);
                        map.put("fastCoin", jobConfig.fastTaskCoin);
                        map.put("permissionTime", 1);
                        map.put("fastTime", 0);
                        map.put("tryTime", 0);
                    }
                } else {
                    map.put("coin", jobConfig.nomalTaskCoin);
                    map.put("fastCoin", jobConfig.fastTaskCoin);
                    map.put("permissionTime", 0);
                    map.put("fastTime", 0);
                    map.put("tryTime", 0);
                }
                break;

            case 7:

                if (level > 0) {
                    map.put("coin", 0);
                    map.put("fastCoin", 0);
                    map.put("permissionTime", 1);
                    map.put("fastTime", 0);
                    map.put("tryTime", 0);

                } else {
                    map.put("fastCoin", 0);
                    map.put("permissionTime", 0);
                    map.put("fastTime", 0);
                    if (vipNum0 > 0) {
                        map.put("coin", 0);
                        map.put("tryTime", 1);
                    } else {
                        map.put("coin", jobConfig.nomalTaskCoin);
                        map.put("tryTime", 0);
                    }
                }
                break;
        }
        return map;
    }

    public void task() {

        List<Job> list= jobRepository.findAllByTaskState();
        for (Job job: list) {
            gets(job.getId());
        }
    }
}
